<?php
    class GP_hooks 
    {
        static $enabled 		= false;
        static $hooks   		= array();
        static $in_progress	    = false;
        
        static $_instance;
		
		// singleton
		public static function &getInstance() 
		{
			if (!self::$_instance instanceof self) {
				self::$_instance = new self();
			}
            return self::$_instance;
		}

        /**
         * Constructor
         *
         */
        function __construct()
        {
            if (false === HOOK_ENABLED) {
                return;
            }
            self::$enabled = true;
            self::run();
        }
        
        /**
         * addHook
         *
         * @access	private
         * @param	when	    (pre | post [system, controller, view])
         * @param	function	function to execute
         * @param	params  	params to allocate to function
         * @return	void
         */  
        
        public static function addHook($when, $function, $params)
        {
            if (false === self::$enabled) {
                return;
            }
            
            $hooks = getvar('**hooks**');
            $md5 = md5($when . $function . $params);
           
            if (null === $hooks) {
                $hooks = array();
            } else {
                if (true === $hooks[$md5]) {
                    return;
                }
            }
            $hooks[$md5] = true;
            $hooks[$when][] = array(
                'function' => $function, 
                'params' => $params
            );
            setvar('**hooks**', $hooks);
        }
      
        // --------------------------------------------------------------------

        /**
         * Run
         *
         * @access	private
         * @return	void
         */  
        public static function run()
        {
            // If hooks are not enabled in the config file
            // there is nothing else to do

            if (false === self::$enabled) {
                return;
            }
            // Grab the "hooks" definition file.
            // If there are no hooks, we're done.

            $hooks = getvar('**hooks**');

            if (null === $hooks) {
                return;
            }
            
            self::$hooks = $hooks;
        }
      
        // --------------------------------------------------------------------

        /**
         * Call Hook
         *
         * Calls a particular hook
         *
         * @access	private
         * @param	string	the hook name
         * @return	mixed
         */
        public static function callHook($when = '')
        {
            if (false === self::$enabled || !isset(self::$hooks[$when])) {
                return false;
            }
            
            if (isset(self::$hooks[$when][0]) && is_array(self::$hooks[$when][0])) {
                foreach (self::$hooks[$when] as $val) {
                    self::runHook($val);
                }
            } else {
                self::runHook(self::$hooks[$when]);
            }
            
            return true;
        }

        // --------------------------------------------------------------------

        /**
         * Run Hook
         *
         * Runs a particular hook
         *
         * @access	private
         * @param	array	the hook details
         * @return	bool
         */
        public static function runHook($data)
        {
            if (!is_array($data) || false === self::$enabled) {
                return false;
            }
            // -----------------------------------
            // Safety - Prevents run-away loops
            // -----------------------------------

            // If the script being called happens to have the same
            // hook call within it a loop can happen

            if (true === self::$in_progress) {
                return;
            }
            
            if (null === $data['file']) {
                return false;
            }
            
            if (!is_file(DIR_HOOKS . $data['file'])) {
                return false;
            }
            
            require_once(DIR_HOOKS . $data['file']);
            
            self::$in_progress = true;
            
            $class		= false;
            $function	= false;
            $params		= '';

            if (isset($data['class']) && $data['class'] != '') {
                $class = $data['class'];
            }

            if (isset($data['function']) && $data['function'] != '') {
                $function = $data['function'];
            }

            if (isset($data['params'])) {
                $params = $data['params'];
            }

            if ($class === false && $function === false) {
                return false;
            }

            if ($class !== false)
            {
                $hookClass = new $class;
                $execHook = $hookClass->$function($params);
            } else {
                $execHook = $function($params);
            }
            
            self::$in_progress = false;
            return $execHook;
        }

    }
?>